package com.atguigu.edu2021.mock.stage;

import com.atguigu.edu2021.mock.bean.OrderInfo;
import com.atguigu.edu2021.mock.bean.PaymentInfo;
import com.atguigu.edu2021.mock.bean.VipChangeDetail;
import com.atguigu.edu2021.mock.config.AppConfig;
import com.atguigu.edu2021.mock.factory.UserSession;
import com.atguigu.edu2021.mock.log.AppCommon;
import com.atguigu.edu2021.mock.log.AppDisplay;
import com.atguigu.edu2021.mock.log.AppMain;
import com.atguigu.edu2021.mock.log.AppPage;
import com.atguigu.edu2021.mock.log.enums.ItemType;
import com.atguigu.edu2021.mock.log.enums.PageId;
import com.atguigu.edu2021.mock.service.OrderInfoService;
import com.atguigu.edu2021.mock.service.PaymentInfoService;
import com.atguigu.edu2021.mock.service.UserInfoService;
import com.atguigu.edu2021.mock.service.VipChangeDetailService;
import com.atguigu.mock.util.LogUtil;
import com.atguigu.mock.util.RanOpt;
import com.atguigu.mock.util.RandomBox;
import com.atguigu.mock.util.RandomNum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;

import static com.atguigu.edu2021.mock.config.EduConstant.*;

@Component("payment")
public class PaymentStage implements Stage {

    @Autowired
    PaymentInfoService paymentInfoService;

    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    UserInfoService userInfoService;

    @Autowired
    VipChangeDetailService vipChangeDetailService;


    @Override
    public boolean handle() {
        if(UserSession.getOrderInfo()==null){
            return false;
        }

        AppMain mainlog = mainlog();
        LogUtil.logToJson(mainlog);

        PaymentInfo paymentInfo = genPaymentInfo();
        paymentInfoService.saveOrUpdate(paymentInfo);

        updateOrderInfo();
        UserSession.setLastPageId(PageId.payment);
        return true;
    }


    private AppMain mainlog(){
        AppCommon appCommon = UserSession.getAppCommon();

        Long orderId = UserSession.getOrderInfo().getId();

        Integer durTime= RandomNum.getRandInt(5000, AppConfig.page_during_max_ms);

        AppPage appPage = AppPage.builder()
                .last_page_id(UserSession.getLastPageId())
                .item(orderId.toString())
                .item_type(ItemType.order_id)
                .during_time(durTime)
                .page_id(PageId.payment).build();

        List<AppDisplay> appDisplayList = AppDisplay.builder().buildList();
        UserSession.addTimeByDuringTime(appPage.getDuring_time());
        Long ts= UserSession.getCurDateTime().getTime();
        AppMain appMain = AppMain.builder().common(appCommon).page(appPage).displays(appDisplayList).ts(ts).build();
        return appMain;

    }


    private PaymentInfo genPaymentInfo(){
        OrderInfo orderInfo = UserSession.getOrderInfo();
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setOrderId(orderInfo.getId());
        paymentInfo.setTradeBody(orderInfo.getTradeBody());
        paymentInfo.setAlipayTradeNo(UUID.randomUUID().toString());


         RandomBox<String> paymentTypeBox=new RandomBox(new RanOpt(PAYMENT_TYPE_ALIPAY,AppConfig.payment_type_weight[0])
                ,new RanOpt(PAYMENT_TYPE_WECHAT,AppConfig.payment_type_weight[1]),
                new RanOpt(PAYMENT_TYPE_UNION,AppConfig.payment_type_weight[2]));
        String paymentType = paymentTypeBox.getRandStringValue();
        paymentInfo.setPaymentType(paymentType);

        paymentInfo.setPaymentStatus(PAYMENT_STATUS_PAID);
        paymentInfo.setCreateTime(UserSession.getCurDateTime());
        paymentInfo.setCallbackTime(DateUtils.addSeconds(UserSession.getCurDateTime(),10) );
        paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
        paymentInfo.setTotalAmount(orderInfo.getFinalAmount());

        return paymentInfo;
    }

    private  void  updateOrderInfo(){
        OrderInfo orderInfo = UserSession.getOrderInfo();
        orderInfo.setOrderStatus(ORDER_STATUS_PAID);
        orderInfo.setUpdateTime(UserSession.getCurDateTime());
        orderInfoService.saveOrUpdate(orderInfo);
        userInfoService.setUserHasCourse(orderInfo.getUserId());
        vipChange(orderInfo);

    }

    private void vipChange(OrderInfo orderInfo){
        Integer[] vipThresholds = AppConfig.vipThreshold;

        OrderInfo  sumOrder = orderInfoService.getOne(new QueryWrapper<OrderInfo>()
                .select(" sum(final_amount) final_amount")
                .eq("user_id", orderInfo.getUserId()).eq("order_status", ORDER_STATUS_PAID));
        BigDecimal sumAmount=sumOrder.getFinalAmount();
        int toVip=0;
        for (int i = 0; i < vipThresholds.length; i++) {
            Integer threshold = vipThresholds[i];
            if(sumAmount.compareTo(BigDecimal.valueOf(threshold) ) >0){
                toVip=i+1;
            }
        }
        Integer fromVip=0 ;
        VipChangeDetail existsVipChangeDetail
                = vipChangeDetailService.getOne(new QueryWrapper<VipChangeDetail>().eq("user_id",orderInfo.getUserId()).orderByDesc("create_time").last(" limit 1"));
        if(existsVipChangeDetail!=null){
            fromVip=existsVipChangeDetail.getToVip();
        }

        VipChangeDetail vipChangeDetail = new VipChangeDetail();
        vipChangeDetail.setFromVip(fromVip);
        vipChangeDetail.setToVip(toVip);
        vipChangeDetail.setUserId(orderInfo.getUserId());
        vipChangeDetail.setCreateTime(UserSession.getCurDateTime());

        vipChangeDetailService.saveOrUpdate(vipChangeDetail);
    }
}
